package cn.dac.shiro;

import cn.dac.exception.ThrErrorCodeException;
import cn.dac.shiro.cache.RedisCacheManager;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 密码错误次数限制登录
 * 配置
 * ShiroConfiguration HashedCredentialsMatcher
 * 错误次数> 1 显示验证码
 * 错误次数> 5 15分钟内不可登陆
 * @author anan
 */

public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
    private static final Logger logger = LoggerFactory.getLogger(RetryLimitHashedCredentialsMatcher.class);
    private Cache<String, AtomicInteger> passwordRetryCache;

    public RetryLimitHashedCredentialsMatcher(RedisCacheManager cacheManager) {
        passwordRetryCache = cacheManager.getCache("password-retry-count");

    }
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token,
                                      AuthenticationInfo info) {
        String loginName = (String) token.getPrincipal();

        boolean matches = super.doCredentialsMatch(token, info);
        if (matches) {
            // clear retry count
            passwordRetryCache.remove(loginName);
        }else {
            // retry count + 1
            AtomicInteger retryCount = passwordRetryCache.get(loginName);

            if (retryCount == null) {
                retryCount = new AtomicInteger(0);
            }
            int nextCount = retryCount.incrementAndGet();
            logger.info("###【密码错误次数】登陆名/错误次数："+loginName+"=="+nextCount);
            SecurityUtils.getSubject().getSession().setAttribute("RETRY_COUNT",nextCount);
            passwordRetryCache.put(loginName, retryCount);
            if (nextCount > 5) {
                // if retry count > 5 throw
                throw new ExcessiveAttemptsException();
            }
            if(nextCount > 1){
                throw new ThrErrorCodeException();
            }
        }
        return matches;
    }
}
